feat: add Teams (Circles) async API#403
Conversation
Implements issue #343 — adds async-only Teams/Circles API to nc_py_api. New module `nc_py_api/teams.py` provides: - Data classes: Circle, Member - Enums: MemberType, MemberLevel, CircleConfig - _AsyncTeamsAPI with methods: available, get_list, create, get_details, destroy, edit_name, edit_description, edit_config, get_members, add_member, add_members, remove_member, set_member_level, confirm_member, join, leave Registered on _AsyncNextcloudBasic (AsyncNextcloud + AsyncNextcloudApp). 17 tests covering both client and AppAPI modes.
for more information, see https://pre-commit.ci
Fix add_member, confirm_member to return Member (API returns single dict, not list). Fix remove_member to return None (API returns empty array). Accept CircleConfig | int in edit_config. Export public classes from __init__.py. Fix hardcoded URL in tests, revert unrelated gfixture_set_env change.
7afd3a8 to
cf167e6
Compare
📝 WalkthroughWalkthroughAdds async Nextcloud Teams (Circles) support: new Changes
Sequence Diagram(s)sequenceDiagram
participant Test as rgba(0,128,255,0.5) Test Suite
participant Client as rgba(0,200,100,0.5) AsyncNextcloud (anc)
participant Server as rgba(255,100,0,0.5) Nextcloud OCS API
participant UserClient as rgba(150,50,200,0.5) AsyncNextcloud (test user)
Test->>Client: anc.teams.create(name, personal?, local?)
Client->>Server: POST /ocs/v2.php/apps/circles/api/v1/circles (body)
Server-->>Client: 201 Created + circle payload
Client-->>Test: Circle object
Test->>Client: anc.teams.add_member(circle_id, user_id)
Client->>Server: POST /ocs/v2.php/apps/circles/api/v1/circles/{id}/members
Server-->>Client: 200 OK + member payload
Client-->>Test: Member object
Test->>UserClient: user.teams.join(circle_id)
UserClient->>Server: POST /ocs/v2.php/apps/circles/api/v1/circles/{id}/join
Server-->>UserClient: 200 OK (or pending request)
UserClient-->>Test: Circle / Member status
Test->>Client: anc.teams.confirm_member(circle_id, member_id)
Client->>Server: POST /ocs/v2.php/apps/circles/api/v1/circles/{id}/members/{mid}/confirm
Server-->>Client: 200 OK + updated member
Client-->>Test: Confirmed Member object
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Add pytest.skip("Teams (Circles) is not installed") guard to every
teams test, matching the pattern used by notes/activity/talk tests.
Install circles app in tests-pgsql and tests-maria CI jobs so tests
actually run on those pipelines, while gracefully skipping on others.
The Circles app processes member removal and join operations asynchronously via HTTP loopback. Without overwrite.cli.url configured, the loopback fails silently and these operations never complete. Also enable circles after the PHP server starts so the app can verify its loopback connectivity at initialization time.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #403 +/- ##
==========================================
+ Coverage 94.47% 94.69% +0.21%
==========================================
Files 46 47 +1
Lines 5359 5575 +216
==========================================
+ Hits 5063 5279 +216
Misses 296 296
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/analysis-coverage.yml:
- Around line 416-417: Add the Circles checkout and enablement to the
tests-client-sqlite job so client-mode Teams tests run under Circles as in
tests-maria/tests-pgsql: ensure the workflow job named tests-client-sqlite
includes the same checkout step for the Circles app and the "Enable Circles"
step that runs the command php occ app:enable circles (same as the existing
Enable Circles step in the diff), mirroring the setup used in
tests-maria/tests-pgsql; also consider doing the same for tests-oci if you want
OCI client-mode coverage.
In `@nc_py_api/teams.py`:
- Around line 114-122: The user_type and level properties currently call
MemberType(self._raw_data.get("userType", 1)) and
MemberLevel(self._raw_data.get("level", 0)) which will raise ValueError if the
API returns unknown enums; update these accessors (user_type and level) to
defensively handle invalid values by catching ValueError (or using the
Enum._missing_ hook) and returning a safe fallback (e.g., MemberType.USER and
MemberLevel.NONE) while still using self._raw_data.get(...) to obtain the raw
value; ensure the change references the same symbols (user_type, level,
MemberType, MemberLevel, and _raw_data) so behavior is forward-compatible with
unexpected API values.
- Around line 138-143: The `@dataclasses.dataclass` decorator on class Circle is
unnecessary because Circle defines a custom __init__ and doesn't use dataclass
features; remove the decorator line above class Circle (and mirror the same
removal you applied to Member) so Circle is a plain class with its existing
__init__ and _raw_data attribute.
- Around line 87-92: The `@dataclasses.dataclass` decorator on class Member is
misleading because Member defines a custom __init__ (and __repr__), so remove
the decorator line from the class definition and keep the existing
__init__/_raw_data handling (or alternatively, if you prefer using dataclass
semantics, replace the custom __init__ and __repr__ with dataclass field
declarations such as raw_data: dict and let dataclass generate
__init__/__repr__); in short, either delete the `@dataclasses.dataclass` decorator
from Member or refactor Member to declare dataclass fields and remove the manual
__init__/__repr__ so the decorator is used correctly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 84095ae1-ec9c-442b-9476-282d80a6c9c2
📒 Files selected for processing (5)
.github/workflows/analysis-coverage.ymlnc_py_api/__init__.pync_py_api/nextcloud.pync_py_api/teams.pytests/actual_tests/teams_test.py
Tests the full request-to-join flow: create circle with REQUEST config, user requests to join (status=Requesting), admin confirms the member (status=Member).
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tests/actual_tests/teams_test.py`:
- Line 121: The assertion currently hardcodes details.owner.user_id == "admin";
replace the hardcoded string with the test's actual acting-user id variable so
the check is environment-agnostic (e.g., assert details.owner.user_id ==
acting_user.user_id or assert details.owner.user_id == current_user.user_id —
locate the variable used in this test that represents the requester/test user
and use that instead of "admin").
- Around line 243-260: AsyncNextcloud instances (anc_user and anc_any) leak HTTP
connection pools because AsyncNextcloud provides no public close API; update the
test to explicitly close the underlying session adapters after using
AsyncNextcloud: wrap the operations that call anc_user.teams.join /
anc_user.teams.leave and anc_any.teams.get_members in try/finally blocks and in
the finally await closing of anc_user._session.adapter and
anc_user._session.adapter_dav (and do the same for anc_any) to ensure adapters
are closed and connections cleaned up.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 91a86c2e-1479-48b1-8406-3c091ea8f5d9
📒 Files selected for processing (1)
tests/actual_tests/teams_test.py
Summary
Closes #343
_AsyncTeamsAPImodule (nc_py_api/teams.py) for managing Nextcloud Teams (Circles)Circle,Memberwith typed propertiesMemberType,MemberLevel,CircleConfig(IntFlag)_AsyncNextcloudBasic— available on bothAsyncNextcloudandAsyncNextcloudAppFollowing the async-only policy for new features — no sync variant.
Test plan
tests/actual_tests/teams_test.pytest_teams_availableandtest_teams_create_destroyrun in both client and AppAPI modes (ancfixture)NextcloudExceptionSummary by CodeRabbit
New Features
Tests
Chores